#include "httpmanager.h"

// 以post的方式发送http请求
HttpManager::HttpManager()
{
    connect(this, &HttpManager::signal_http_finish, this, &HttpManager::slot_http_finish);
}

 // 发送信号通知指定模块http响应结束
void HttpManager::slot_http_finish(ReqId id, QString res, ErrorCodes err, Modules mod)
{
    if (mod == Modules::REGISTERMOD){
        // 发送信号通知指定模块http响应结束
        emit signal_reg_mod_finish(id, res, err);
    }

    if(mod == Modules::RESETMOD){
        // 发送信号通知指定模块http响应结束
        emit signal_reset_mod_finish(id, res, err);
    }

    if (mod == Modules::LOGINMOD) {
        // 发送信号通知指定模块http响应结束
        emit signal_login_mod_finish(id, res, err);
    }
}


HttpManager::~HttpManager()
{

}

void HttpManager::PostHttpReq(QUrl url, QJsonObject json, ReqId req_id, Modules mod)
{
    QByteArray data = QJsonDocument(json).toJson();
    QNetworkRequest request(url);
    // http请求的头部类型
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    // http请求内容的长度
    request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number( data.length() ) );
    
    // 通过HttpManager的this指针生成一个智能对象，将其给一个lamda表达式，防止在lamda表达式调用完之前，HttpManager对象被回收了，
    // 底层lamda表达式在调用时用到HttpManager的数据就会产生异常崩溃
    auto self = shared_from_this(); // 为了使引用计数同步
    
    QNetworkReply* reply = m_manager.post(request, data);
    // 只用一个this去捕获是不安全的，如果HttpManager被删除了，下面的lamda回调还会继续用到HttpManager里面的成员
    // 触发回调时有可能程序会崩溃或数据紊乱
    // 为了保证在回调触发之前，HttpManager不能被删除，所以在外部使用的时候需要采用一个智能指针去管理
    // 在内部需要根据this生成
    connect(reply, &QNetworkReply::finished, [self, reply, req_id, mod]() {
        // 处理错误情况
        if (reply->error() != QNetworkReply::NoError) {
            qDebug() << reply->errorString();
            // 发送信号通知http请求处理完成
            emit self->signal_http_finish(req_id, "", ErrorCodes::ERR_NETWORK, mod);
            reply->deleteLater();
            return ;
        }

        // 未发生错误
        QString res = reply->readAll();
        // 发送信号通知http请求处理完成
        emit self->signal_http_finish(req_id, res, ErrorCodes::SUCCESS, mod);
        reply->deleteLater();
        return ;
    });
}
